#pragma once

#include <QtGui/QMainWindow>

#include "State.hpp"
#include "ProjectItem.hpp"
#include "ErrorModel.hpp"




namespace Engine
{
	namespace Edit
	{
		/**
		 * This class implements and enforces the basic functionality for any view in this application,
		 * that somehow displays a ProjectItem from the project tree.
		 *
		 * Every view is bound to an item from the point of creation: it can never be bound to another
		 * during it's lifetime.
		 *
		 * Every view uses an ErrorModel to communicate errors related to that view to a higher level.
		 * This model is displayed (in conjunction with others) in a special view.
		 */
		class DocumentWindow
			: public QMainWindow
		{
			Q_OBJECT

		public:

			DocumentWindow(ProjectItem::ptr item, QWidget* parent);
			virtual ~DocumentWindow();



			/**
			* @returns the ProjectItem this DocumentView displays
			*/
			ProjectItem::ptr item() const;

			/**
			 * @returns the ErrorModel for reading purposes
			 */
			ErrorModel::const_ptr errorModel() const;



			/**
			 * Changes the state of the window.
			 *
			 * When the state is changed to debugging, every view is required to enter
			 * a read-only mode where the user is unable to change anything at all.
			 *
			 * Editing on the other hand is the default mode.
			 */
			virtual void changeState(State::Type state);



			/**
			 * Saves the document that is shown in this view.
			 * After calling this function, isWindowModified() must return false.
			 */
			virtual void save() = 0;

		signals:

			/**
			 * This signal is emitted when the user has modified the displayed data.
			 */
			void modified(DocumentWindow*);

			/**
			 * This signal is emitted when the window system decides to
			 * close this window AND the user has agreed to it.
			 */
			void closed(DocumentWindow*);

		protected:

			/**
			 * Asks the user if the current project should be closed.
			 * Is only done in case there is a project and it has been modified.
			 *
			 * @returns true when the project can be closed
			 * @returns false otherwise
			 */
			bool canBeClosed();

			/**
			 * Tries to close the document.
			 * @returns if this was successfull or not
			 */
			bool closeDocument();

			/**
			 * This event is called whenever the window shall be closed.
			 * In case the document has been notified, the user is asked
			 * if he wants to save those changes, discard the changes
			 * or cancel the operation (ie. the window doesn't close).
			 */
			virtual void closeEvent(QCloseEvent* event);

			/**
			 * This slot is bound to the modified signal of the item.
			 */
			ProjectItem::Result itemModified(ProjectItem::weak_ptr sender, ProjectItem::weak_ptr item, ProjectItem::Action action);

			/**
			 * This slot sets the window's title.
			 */
			void setTitle();

		protected:

			/// The current state of the window
			State::Type           m_state;

			// A document view always displays one specific item of the
			// project tree, therefore we can store the pointer here
			const ProjectItem::ptr   m_item;

			// A document view also maintains a model for all current errors
			const ErrorModel::ptr    m_errors;

			/// This dummy can be used to automatically disconnect
			/// slots upon destruction of the window
			const boost::shared_ptr<char>   m_dummy;
		};
		///////////////////////////////////////////////////////////////////////////////////////////
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
